/*
 * General time and date functions
 */

#include "TimeDate.h"
#include "Types.h"
#include "ZSysgen.h"
#include "ZTypes.h"
#include "ZClock.h"

/*
 * Private function to get the day of the week 
 * Algorithm borrowed from http://everything2.com/title/how%2520to%2520calculate%2520the%2520day%2520of%2520the%2520week%2520for%2520a%2520given%2520date
 *
 * Params:
 *		day - day of the month
 *		month
 *		year
 *
 * Returns:
 * 		1 = Sunday
 *		2 = Monday
 *		3 = Tuesday
 *		4 = Wednesday
 *		5 = Thursday
 *		6 = Friday
 *		7 = Saturday
 */
int getDayOfWeek(int day, int month, int year)
{
	if (month < 3)
     {
           month = month + 12;
           year = year - 1;
     }
     return (
             day
             + (2 * month)
             + (int)(6 * (month + 1) / 10)
             + year
             + (int)(year / 4)
             - (int)(year / 100)
             + (int)(year / 400)
             + 1
            ) % 7;
}


/*
 * Public function to get the last date of any month
 *
 * Params:
 *		month
 *		year
 *
 * Returns:
 * 		The last date of the month for that year (1-31)
 */
int getLastDayInMonth(int month, int year)
{
	if(month == 2)
	{
		//Check if leap year
		if(isLeapYear(year) == TRUE)
		{
			return 29;
		}
		else
		{
			return 28;
		}
	}

	// Thirty days hath:
		//September		//April		//June	and		//November
	if(month == 9 || month == 4 || month == 6 || month == 11)
	{
		return 30;
	}

	// The rest have 31
	return 31;
}


/*
 * Public function to determine whether or not it is a leap year
 *
 * Params:
 *		year
 *
 * Returns:
 * 		TRUE or FALSE
 */
BOOL isLeapYear(int year)
{
	if(year % 4 == 0)
	{
		if(year % 100 == 0)
		{
			//This is a century year
			if(year % 400 == 0)
			{
				return TRUE;
			}
			else
			{
				return FALSE;
			}
		}
		else
		{
			return TRUE;
		}
	}
	else
	{
		return FALSE;
	}
}


/*
 * Public function to determind whether or not the date passed in is 
 * in the daylight saving period of the year
 *
 * Params:
 *		day - day of the month
 *		month
 *		year
 *
 * Returns:
 * 		TRUE or FALSE
 */
BOOL inDaylightSaving(int day, int month, int year)
{
	// In the US, this runs from the second Sunday in March to the first Sunday in November
	int dateStart;
	int dateEnd;
	int monthStart = 3;
	int monthEnd = 11;
	
	// Need to find the start date

	//Looking for the second Sunday in March
	// The earliest it could be is on the eighth
	int dayOfWeek = 0;
	dateStart = 7;
	while(dayOfWeek != 1)
	{
		dateStart++; //We start searching at the 8th for a Sunday
		dayOfWeek = getDayOfWeek(dateStart, monthStart, year);
	}
	// dateStart should now be the second Sunday of March

	// Now find the end date

	//Looking for the first Sunday in November
	// Could be the very first day of the month
	dayOfWeek = 0;
	dateEnd = 0;
	while(dayOfWeek != 1)
	{
		dateEnd++; //Start search on the 1st
		dayOfWeek = getDayOfWeek(dateEnd, monthEnd, year);
	}
	// endDate shoudl now be first Sunday of November

	if(month > monthStart && month < monthEnd)
	{
		//We are well within the bounds
		return TRUE;
	}
	if(month == monthStart)
	{
		//It is March something
		if(day >= dateStart)
		{
			// Note that this starts daylight savings time at midnight, not 2AM as it should
			// If this really bothers anyone, change it yourself
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}
	if(month == monthEnd)
	{
		//It is November
		if(day <= dateEnd)
		{
			// Again, this is terminated at midnight when it should be 2AM
			return TRUE;
		}
		else
		{
			return FALSE;
		}
	}

	return FALSE;
}


/*
 * Public function to estimate whether the clock time
 * appears to be a valide value
 *
 * Params:
 *
 * Returns:
 * 		TRUE or FALSE
 */
BOOL isClockTimeValid()
{
	RZK_CLOCKPARAMS_t sysTime;

	RZKGetClock(&sysTime);

	//NOTE: This is a really shitty way of doing this
	//but it is actually a pretty good quick and dirty solution

	if(sysTime.uCurr_Year >= 2009 && sysTime.uCurr_Month >= 4)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}